正弦 ROM
让我们假设您想要生成一个正弦波,并且还有它的滤波版本(这在实际中完全没用,但让我们以此为例)。
| 参数名称 | 类型 | 描述 | 
|---|---|---|
| resolutionWidth | Int | 用于表示数值的位宽 | 
| sampleCount | Int | 一个正弦周期内的采样点数 | 
| IO名称 | 方向 | 类型 | 描述 | 
|---|---|---|---|
| sin | out | SInt(resolutionWidth bits) | 作为正弦波的输出 | 
| sinFiltered | out | SInt(resolutionWidth bits) | 作为滤波后正弦波的输出 | 
那么让我们定义一个 Component :
case class SineRom(resolutionWidth: Int, sampleCount: Int) extends Component {
  val io = new Bundle {
    val sin = out SInt(resolutionWidth bits)
    val sinFiltered = out SInt(resolutionWidth bits)
  }
...
为了在 sin 输出端口上输出正弦波,您可以定义一个 ROM,其包含正弦波一个周期内所有采样点(可能只是四分之一,但让我们以最简单的方式做事)。然后你可以用相位计数器读取该ROM,这将生成你的正弦波。
  // Calculate values for the lookup table
  def sinTable = for(sampleIndex <- 0 until sampleCount) yield {
    val sinValue = Math.sin(2 * Math.PI * sampleIndex / sampleCount)
    S((sinValue * ((1<<resolutionWidth)/2-1)).toInt,resolutionWidth bits)
  }
  val rom =  Mem(SInt(resolutionWidth bits),initialContent = sinTable)
  val phase = Reg(UInt(log2Up(sampleCount) bits)) init 0
  phase := phase + 1
  io.sin := rom.readSync(phase)
随后生成 sinFiltered ,例如您可以使用一个一阶低通滤波器:
  io.sinFiltered := RegNext(io.sinFiltered  - (io.sinFiltered  >> 5) + (io.sin >> 5)) init 0
这是完整的代码:
case class SineRom(resolutionWidth: Int, sampleCount: Int) extends Component {
  val io = new Bundle {
    val sin = out SInt(resolutionWidth bits)
    val sinFiltered = out SInt(resolutionWidth bits)
  }
  // Calculate values for the lookup table
  def sinTable = for(sampleIndex <- 0 until sampleCount) yield {
    val sinValue = Math.sin(2 * Math.PI * sampleIndex / sampleCount)
    S((sinValue * ((1<<resolutionWidth)/2-1)).toInt,resolutionWidth bits)
  }
  val rom =  Mem(SInt(resolutionWidth bits),initialContent = sinTable)
  val phase = Reg(UInt(log2Up(sampleCount) bits)) init 0
  phase := phase + 1
  io.sin := rom.readSync(phase)
  io.sinFiltered := RegNext(io.sinFiltered  - (io.sinFiltered  >> 5) + (io.sin >> 5)) init 0
}